package com.adam.example.search;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.HighlightField;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.json.JsonData;
import com.adam.example.ElasticsearchClientHolder;
import com.adam.example.types.Book;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SearchBookExample {

    public static void main(String[] args) throws IOException {
        ElasticsearchClient client = ElasticsearchClientHolder.getINSTANCE().initializeAndGetClient();

        SearchRequest searchRequest = SearchRequest.of(builder -> builder
                .index("test_books")
                        .query(queryBuilder -> queryBuilder
                                //全文查询
//                                .match(matchQueryBuilder -> matchQueryBuilder
//                                        .field("title").query("java python").operator(Operator.Or)
//                                )
//                                .matchAll(matchAllQueryBuilder -> matchAllQueryBuilder)
//                                .matchPhrase(matchPhraseQueryBuilder -> matchPhraseQueryBuilder
//                                        .field("description").query("Spring Cloud")
//                                )
//                                .matchPhrasePrefix(matchPhrasePrefixQueryBuilder -> matchPhrasePrefixQueryBuilder
//                                        .field("description").query("Spring Cl")
//                                )
//                                .multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder
//                                        .fields("title", "description").query("Spring Cloud")
//                                )
                                //common terms query在8.0版本被完全移除，查询会报错
//                                .common(commonTermsQueryBuilder -> commonTermsQueryBuilder
//                                        .field("title").query("java and python")
//                                        .cutoffFrequency(0.3).lowFreqOperator(Operator.Or).highFreqOperator(Operator.And)
//                                )
//                                .queryString(queryStringQueryBuilder -> queryStringQueryBuilder
//                                        .query("+java -python").fields("title^1.2", "description")
//                                )
//                                .simpleQueryString(simpleQueryStringQueryBuilder -> simpleQueryStringQueryBuilder
//                                        .query("+java -python").fields("title^1.2", "description")
//                                )

                                //词项查询
//                                .term(termQueryBuilder -> termQueryBuilder
//                                        .field("title").value("java")
//                                )
//                                .terms(termsQueryBuilder -> termsQueryBuilder
//                                        .field("title").terms(termsQueryFieldBuilder -> termsQueryFieldBuilder
//                                                .value(Arrays.asList(FieldValue.of("java"), FieldValue.of("python")))
//                                        )
//                                )
//                                .range(rangeQueryBuilder -> rangeQueryBuilder
//                                        .field("price").gt(JsonData.of(50)).lt(JsonData.of(80))
//                                )
//                                .range(rangeQueryBuilder -> rangeQueryBuilder
//                                        .field("publish_time").gt(JsonData.of("2014-01-01")).lt(JsonData.of("2016-12-31"))
//                                )
//                                .exists(existsQueryBuilder -> existsQueryBuilder
//                                        .field("language")
//                                )
//                                .prefix(prefixQueryBuilder -> prefixQueryBuilder
//                                        .field("title").value("jav")
//                                )
//                                .wildcard(wildcardQueryBuilder -> wildcardQueryBuilder
//                                        .field("author").value("张若?")
//                                )
//                                .regexp(regexpQueryBuilder -> regexpQueryBuilder
//                                        .field("author").value("Bru\\w?e Eck\\w?l")
//                                )
//                                .fuzzy(fuzzyQueryBuilder -> fuzzyQueryBuilder
//                                        .field("title").value("javascritp").fuzziness("2")
//                                )
                                //type query已废弃
//                                .type(typeQueryBuilder -> typeQueryBuilder
//                                        .value("_doc")
//                                )
//                                .ids(idsQueryBuilder -> idsQueryBuilder
//                                        .values("1", "4", "6")
//                                )

                                //复合查询
//                                .constantScore(constantScoreQueryBuilder -> constantScoreQueryBuilder
//                                        .filter(queryBuilder1 -> queryBuilder1
//                                                .term(termQueryBuilder -> termQueryBuilder
//                                                        .field("title").value("java")
//                                                )
//                                        ).boost(1.2f)
//                                )
//                                .disMax(disMaxQueryBuilder -> disMaxQueryBuilder
//                                        .queries(queryBuilder1 -> queryBuilder1
//                                                .term(termQueryBuilder -> termQueryBuilder
//                                                        .field("title").value("java")
//                                                )
//                                        )
//                                        .queries(queryBuilder1 -> queryBuilder1
//                                                .term(termQueryBuilder -> termQueryBuilder
//                                                        .field("title").value("python")
//                                                )
//                                        )
//                                        .tieBreaker(0.7)
//                                )
//                                .bool(boolQueryBuilder -> boolQueryBuilder
//                                        .must(queryBuilder1 -> queryBuilder1
//                                                .term(termQueryBuilder -> termQueryBuilder
//                                                        .field("title").value("java")
//                                                )
//                                        )
//                                        .mustNot(queryBuilder1 -> queryBuilder1
//                                                .term(termQueryBuilder -> termQueryBuilder
//                                                        .field("title").value("python")
//                                                )
//                                        )
//                                        .should(queryBuilder1 -> queryBuilder1
//                                                .range(rangeQueryBuilder -> rangeQueryBuilder
//                                                        .field("price").gt(JsonData.of(50))
//                                                        .lt(JsonData.of(80))
//                                                )
//                                        )
//                                )
                                //不存在indices query
//                                .functionScore(functionScoreQueryBuilder -> functionScoreQueryBuilder
//                                        .query(queryBuilder1 -> queryBuilder1
//                                                .match(matchQueryBuilder -> matchQueryBuilder
//                                                        .field("title").query("java")
//                                                )
//                                        )
//                                        .functions(functionScoreBuilder -> functionScoreBuilder
//                                                .linear(decayFunctionBuilder -> decayFunctionBuilder
//                                                        .field("price")
//                                                        .placement(decayPlacementBuilder -> decayPlacementBuilder
//                                                                .origin(JsonData.of(0)).scale(JsonData.of(1))
//                                                                .decay(0.99999999)
//                                                        )
//                                                )
//                                        )
//                                )
//                                .boosting(boostingQueryBuilder -> boostingQueryBuilder
//                                        .positive(queryBuilder1 -> queryBuilder1
//                                                .match(matchQueryBuilder -> matchQueryBuilder
//                                                        .field("title").query("python")
//                                                )
//                                        )
//                                        .negative(queryBuilder1 -> queryBuilder1
//                                                .range(rangeQueryBuilder -> rangeQueryBuilder
//                                                        .field("publish_time").lte(JsonData.of("2015-01-01"))
//                                                )
//                                        )
//                                        .negativeBoost(0.2)
//                                )
//                                .moreLikeThis(moreLikeThisQueryBuilder -> moreLikeThisQueryBuilder
//                                        .fields("title", "description")
//                                        .like(likeBuilder -> likeBuilder
//                                                .text("python")
//                                        )
//                                        .minDocFreq(2).minTermFreq(1)
//                                )
                                .script(scriptQueryBuilder -> scriptQueryBuilder
                                        .script(scriptBuilder -> scriptBuilder
                                                .inline(inlineScriptBuilder -> inlineScriptBuilder
                                                        .source("doc['price'].value > 80")
                                                )
                                        )
                                )
                )
                .highlight(highlightBuilder -> highlightBuilder
                        .fields("title", HighlightField.of(highlightFieldBuilder -> highlightFieldBuilder
                                .preTags("<span>").postTags("</span>")
                        ))
                        .fields("description", HighlightField.of(highlightFieldBuilder -> highlightFieldBuilder
                                .preTags("<span>").postTags("</span>")
                        ))
                        .requireFieldMatch(false)
                )
        );

        SearchResponse<Book> searchResponse = client.search(searchRequest, Book.class);
        HitsMetadata<Book> hitsMetadata = searchResponse.hits();
        System.out.println("搜索到" + hitsMetadata.total().value() + "条数据");
        List<Hit<Book>> bookHitList = hitsMetadata.hits();
        for(int i=0;i<bookHitList.size();i++) {
            Hit<Book> bookHit = bookHitList.get(i);
            Book book = bookHit.source();
            System.out.println("文档[" + (i+1) + "][评分" + bookHit.score() + "]:" + book);
            Map<String, List<String>> highlightMap = bookHit.highlight();
            Set<Map.Entry<String, List<String>>> entrySet = highlightMap.entrySet();
            for(int j=0;j< entrySet.size();j++) {
                Map.Entry<String, List<String>> entry = (Map.Entry<String, List<String>>) entrySet.toArray()[j];
                System.out.println("高亮信息：字段=" + entry.getKey() + ",内容=" + entry.getValue());
            }
        }

        ElasticsearchClientHolder.getINSTANCE().close();
    }

}
